<script lang="ts" setup>
import { reactive, ref, onMounted } from "vue"
import { Upload, VideoPause, VideoPlay } from "@element-plus/icons-vue"
// import { genFileId } from "element-plus"
import type { UploadFile, UploadFiles, UploadInstance, UploadRawFile } from "element-plus"
import * as audio from "@/api/audio"
import { ElMessage, ElLoading } from "element-plus"
import type { FileRecordRequestData, FileRecord } from "@/api/audio/types/audio"

const searchData = reactive({ title: "", desc: "" })

const uploadDialogVisible = ref(false)
const showUploadDialog = () => {
  uploadDialogVisible.value = true
  upload?.value?.clearFiles()
  audioDesc.value = ""
}
const audioDesc = ref("")
const upload = ref<UploadInstance>()
// const handleExceed: UploadProps["onExceed"] = (files) => {
//   upload.value!.clearFiles()
//   const file = files[0] as UploadRawFile
//   file.uid = genFileId()
//   upload.value!.handleStart(file)
// }
const fileListLength = ref(0)
const handleChange = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
  fileListLength.value = uploadFiles.length
}
const handleRemove = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
  fileListLength.value = uploadFiles.length
}

const submitUpload = () => {
  if (!audioDesc.value) {
    ElMessage.error(`请先填写文件描述！`)
    return
  }
  if (fileListLength.value == 0) {
    ElMessage.error(`请先选择要上传的文件！`)
    return
  }
  unuploadedFileCount.value = fileListLength.value
  upload.value!.submit()
}
const unuploadedFileCount = ref(0)
const beforeUpload = (rawFile: UploadRawFile) => {
  const data = new FormData()
  console.log(rawFile)
  data.append("file", rawFile)
  data.append(
    "body",
    JSON.stringify({
      title: rawFile.name,
      desc: audioDesc.value
    })
  )
  const loadingInstance = ElLoading.service({ text: "正在上传..." })
  audio
    .audio(data)
    .catch((res) => {
      ElMessage.error(`文件上传失败！${res?.msg || ""}`)
    })
    .finally(() => {
      unuploadedFileCount.value--
      if (!unuploadedFileCount.value) {
        listAudio()
        uploadDialogVisible.value = false
        loadingInstance.close()
      }
    })
  return false
}

const cancelUpload = () => {
  uploadDialogVisible.value = false
}

const tableData = reactive<FileRecord[]>([])
const total = ref(0)
const pageSize = ref(10)
const currentPage = ref(1)
let selectRows: FileRecord[] = []
const tableSelection = (data: FileRecord[]) => {
  selectRows = data
}
const delRows = () => {
  if (selectRows && selectRows.length > 0) {
    const ids = selectRows.map((value) => value.id)
    audio
      .multiDel(ids)
      .then(() => {
        listAudio()
      })
      .catch((res) => {
        ElMessage.error(`文件删除失败！${res?.msg || ""}`)
      })
  } else {
    ElMessage.error(`请先选择要删除的文件！`)
  }
}

const listAudio = () => {
  const data: FileRecordRequestData = {
    offset: (currentPage.value - 1) * pageSize.value,
    step: pageSize.value,
    title: searchData.title,
    desc: searchData.desc
  }
  audio
    .audios(data)
    .then((res) => {
      tableData.length = 0
      total.value = res.total
      if (res?.data instanceof Array) {
        tableData.push(...res.data)
      }
    })
    .catch((res) => {
      ElMessage.error(`查询音频文件列表失败！${res?.msg || ""}`)
    })
}

const clearSearchData = () => {
  searchData.desc = ""
  searchData.title = ""
  currentPage.value = 1
  listAudio()
}

const pageSizeChange = () => {
  currentPage.value = 1
  listAudio()
}

onMounted(listAudio)

const delAudio = (id: string) => {
  audio
    .del(id)
    .then(listAudio)
    .catch((res) => {
      ElMessage.error(`删除音频文件失败！${res?.msg || ""}`)
    })
}

const currentAudio = reactive({ title: "", desc: "", id: 0 })
let source: AudioBufferSourceNode | undefined = undefined
const context = new AudioContext()

const startAudio = (row: FileRecord) => {
  stopAudio()
  const loadingInstance = ElLoading.service({ text: "正在缓冲..." })
  audio
    .play(String(row.id))
    .then((res) => res.data)
    .then((arrayBuffer) => context.decodeAudioData(arrayBuffer))
    .then((audioBuffer) => {
      loadingInstance.close()
      source = context.createBufferSource()
      source.buffer = audioBuffer
      source.connect(context.destination)
      source.start()
      audioState.value = "running"
      currentAudio.title = row.title
      currentAudio.desc = row.desc
      currentAudio.id = row.id
      listAudio()
    })
    .catch(() => {
      loadingInstance.close()
      ElMessage.error(`播放音频文件失败！`)
    })
}
const stopAudio = () => {
  console.log("stopAudio", currentAudio)
  source?.stop()
  source = undefined
  currentAudio.title = ""
  currentAudio.desc = ""
  currentAudio.id = 0
}

const audioState = ref("")
const toggleAudio = () => {
  console.log("toggle", currentAudio)
  if (context.state === "running") {
    context.suspend()
    audioState.value = "suspended"
  } else if (context.state === "suspended") {
    context.resume()
    audioState.value = "running"
  }
}

const exportLogs = () => {
  audio.exportLogs().catch((res) => {
    ElMessage.error(`导出播放记录失败！${res.msg}`)
  })
}
</script>

<template>
  <div class="app-container">
    <el-card shadow="never" class="search-wrapper">
      <div class="flex flex-row overflow-hidden">
        <el-form class="flex flex-row gap-x-4 mr-4" ref="searchFormRef" :model="searchData" label-position="top">
          <el-form-item class="w-64" prop="title" label="文件名">
            <el-input v-model="searchData.title" placeholder="请输入" />
          </el-form-item>
          <el-form-item class="w-64" prop="desc" label="文件描述">
            <el-input v-model="searchData.desc" placeholder="请输入" />
          </el-form-item>
        </el-form>
        <el-button class="self-end mb-[18px]" type="primary" @click="listAudio">确定</el-button>
        <el-button class="self-end mb-[18px]" @click="clearSearchData">重置</el-button>
        <el-button class="self-end mb-[18px] ml-auto" :icon="Upload" @click="showUploadDialog">上传</el-button>
        <div
          v-if="currentAudio.title"
          class="self-end mb-[18px] ml-[24px] h-[64px] px-2 gap-x-2 flex flex-row-reverse flex-grow overflow-hidden border-dashed border border-gray rounded"
        >
          <el-icon :size="36" class="self-center cursor-pointer" @click="toggleAudio"
            ><VideoPlay v-if="audioState == 'suspended'" class="text-blue-400" /><VideoPause
              v-if="audioState == 'running'"
              class="text-blue-400"
            />
          </el-icon>
          <div class="self-center flex-grow overflow-hidden">
            <!-- <div class="text-gray text-sm"></div> -->
            <el-tooltip effect="dark" :content="currentAudio.title" placement="bottom">
              <div class="overflow-hidden truncate text-sm text-black">{{ currentAudio.title }}</div>
            </el-tooltip>
            <el-tooltip effect="dark" :content="currentAudio.desc" placement="bottom">
              <div class="truncate text-gray text-sm">{{ currentAudio.desc }}</div>
            </el-tooltip>
          </div>
        </div>
      </div>
    </el-card>
    <el-card shadow="never">
      <el-popconfirm title="确定删除？" confirm-button-text="确定" cancel-button-text="取消" @confirm="delRows">
        <template #reference>
          <el-button class="mb-2 float-right" type="danger">多选删除</el-button>
        </template>
      </el-popconfirm>
      <el-button class="mb-2 mr-2 float-right" type="primary" @click="exportLogs">导出播放记录</el-button>
      <!-- <el-button class="my-2 float-right" type="danger" @click="delRows">多选删除</el-button> -->
      <el-table :data="tableData" @selection-change="tableSelection">
        <el-table-column type="selection" width="55" />
        <el-table-column prop="title" label="文件名" show-overflow-tooltip />
        <el-table-column prop="desc" label="文件描述" show-overflow-tooltip />
        <el-table-column prop="playcount" label="播放次数" width="100" />
        <el-table-column prop="createtime" label="上传时间" width="160" />
        <el-table-column label="操作" width="220">
          <template #default="scope">
            <el-button type="primary" text size="small" @click="startAudio(scope.row)">播放</el-button>
            <el-button text size="small" @click="$router.push({ name: 'AudioPlayLog', params: { id: scope.row.id } })"
              >播放记录</el-button
            >

            <el-popconfirm
              title="确定删除？"
              confirm-button-text="确定"
              cancel-button-text="取消"
              @confirm="delAudio(scope.row.id)"
            >
              <template #reference>
                <el-button type="danger" text size="small">删除</el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
      <div class="flex flex-row-reverse mt-[8px]">
        <el-pagination
          v-if="total > 0"
          layout="prev,pager,next,sizes"
          :total="total"
          v-model:page-size="pageSize"
          :page-sizes="[3, 10, 20, 30, 40, 50]"
          @size-change="pageSizeChange"
          v-model:current-page="currentPage"
          @current-change="listAudio"
        />
      </div>
    </el-card>
  </div>
  <el-dialog title="上传音频文件" v-model="uploadDialogVisible">
    <el-form label-position="top">
      <el-form-item label="文件描述">
        <el-input v-model="audioDesc" />
      </el-form-item>
    </el-form>
    <el-upload
      ref="upload"
      action=""
      multiple
      :limit="0"
      :on-change="handleChange"
      :on-remove="handleRemove"
      :before-upload="beforeUpload"
      :auto-upload="false"
    >
      <template #trigger>
        <el-button>选择文件</el-button>
      </template>
    </el-upload>
    <template #footer>
      <el-button type="primary" @click="submitUpload"> 上传 </el-button>
      <el-button @click="cancelUpload"> 取消 </el-button>
    </template>
  </el-dialog>
</template>

<style lang="scss" scoped>
.search-wrapper {
  margin-bottom: 20px;
  :deep(.el-card__body) {
    padding-bottom: 2px;
  }
}
</style>
